package cn.xeblog.plugin.tools.read.page;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.xeblog.plugin.cache.DataCache;
import cn.xeblog.plugin.tools.read.api.LegadoApi;
import cn.xeblog.plugin.tools.read.entity.Book;
import cn.xeblog.plugin.tools.read.entity.BookType;
import cn.xeblog.plugin.tools.read.entity.LegadoBook;
import cn.xeblog.plugin.tools.read.error.LegadoApiException;
import cn.xeblog.plugin.tools.read.ui.AutoNewlineTextPane;
import cn.xeblog.plugin.tools.read.ui.HardReadWidget;
import cn.xeblog.plugin.tools.read.util.ChapterUtil;
import cn.xeblog.plugin.tools.read.util.KeyFormatUtil;
import cn.xeblog.plugin.util.NotifyUtils;
import com.intellij.ui.components.JBLoadingPanel;
import com.intellij.ui.components.JBScrollPane;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.KeyEventPostProcessor;
import java.awt.KeyboardFocusManager;
import java.awt.event.KeyEvent;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

/**
 * 阅读器页面
 *
 * @author LYF
 * @date 2022-07-18
 */
public class ReadPage implements IPage {

    /**
     * 带加载的阅读器面板
     */
    private JBLoadingPanel readPanel;
    /**
     * 章节标题
     */
    private JLabel title;
    /**
     * 小说正文
     */
    private JTextPane textJta;
    /**
     * 困难模式阅读部件（即idea状态条）
     */
    private final HardReadWidget hardReadWidget = HardReadWidget.create();
    /**
     * 上一页
     */
    private JButton lastPageButton;
    /**
     * 下一页
     */
    private JButton nextPageButton;
    /**
     * 当前阅读的书籍
     */
    private final Book book;
    /**
     * 章节阅读工具
     */
    private ChapterUtil chapterUtil;
    /**
     * 本页面是否显示
     */
    private boolean isShow = false;
    /**
     * 快捷键监听
     */
    private KeyEventPostProcessor processor;
    /**
     * 翻页定时器
     */
    private ScheduledThreadPoolExecutor scheduler;

    /**
     * 初始化书籍
     *
     * @param book 书籍信息
     */
    private ReadPage(Book book) {
        this.book = book;
    }

    /**
     * 获取阅读器页面
     *
     * @param book 书籍信息
     * @return 阅读器页面
     */
    public static ReadPage getInstance(Book book) {
        ReadPage instance = UIManager.readPage;
        // 有就获取，没有就创建
        if (instance != null) {
            if (UIManager.readPage.getBook().equals(book)) {
                return instance;
            }
            // 清空快捷键监听
            instance.cleanProcessor();
        }

        return new ReadPage(book);
    }

    /**
     * 清空快捷键监听
     */
    private void cleanProcessor() {
        // 为空，跳过
        if (processor == null) {
            return;
        }

        // 清空当前快捷键监听
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.removeKeyEventPostProcessor(processor);
    }

    @Override
    public void show() {
        // 是否初始化
        boolean isInit = (readPanel == null);
        // 初始化时，创建一个带加载的阅读器面板
        if (isInit) {
            readPanel = new JBLoadingPanel(new BorderLayout(), DataCache.project);
            readPanel.setBounds(10, 10, 350, 220);
        }
        // 展示面板
        UIManager.showPage(readPanel, 370, 220);
        // 开始加载
        readPanel.startLoading();
        ThreadUtil.execute(() -> {
            // 当为legado书籍时更新书籍进度，失败则返回书架
            if (BookType.LEGADO == book.getType() && !updateBookProgress()) {
                SwingUtilities.invokeLater(() -> {
                    backBookshelf();
                    readPanel = null;
                });
                return;
            }

            SwingUtilities.invokeLater(() -> {
                // 初始化界面
                if (isInit) {
                    initUI();
                } else {
                    // 设置章节工具类实例
                    chapterUtil = new ChapterUtil(book);
                    // 设置文本内容
                    setText();
                }
                if (readPanel != null) {
                    // 结束加载
                    readPanel.stopLoading();
                    isShow = true;
                }
            });
        });
    }

    @Override
    public void initUI() {
        try {
            book.generateChapter();
            chapterUtil = new ChapterUtil(book);
            // 章节标题
            title = new JLabel();
            title.setHorizontalAlignment(SwingConstants.CENTER);
            title.setBorder(BorderFactory.createEmptyBorder(0, 0, 5, 0));
            readPanel.add(title, BorderLayout.NORTH);
            // 正文
            textJta = new AutoNewlineTextPane();
            textJta.setEditable(false);
            textJta.setFont(new Font("", Font.PLAIN, 12));
            if (chapterUtil != null && CollUtil.isNotEmpty(book.getChapters())) {
                setText();
            }
            textJta.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            readPanel.add(new JBScrollPane(textJta), BorderLayout.CENTER);

            // 操作面板
            JPanel optPanel = new JPanel();
            optPanel.add(getLastPageButton());
            optPanel.add(getNextPageButton());
            optPanel.add(getModelButton());
            optPanel.add(getDirectoryButton());
            optPanel.add(getBookshelfButton());
            optPanel.add(getHomeButton());
            readPanel.add(optPanel, BorderLayout.SOUTH);
            readPanel.updateUI();

            // 添加热键监听
            addKeyEventPostProcessor();
        } catch (Exception e) {
            NotifyUtils.warn("", "章节目录解析失败！");
            readPanel = null;
            backBookshelf();
        }
    }

    public Book getBook() {
        return this.book;
    }

    /**
     * 更新章节读取进度
     *
     * @param index 章节索引
     * @param mode  mode 模式，0：初始化；1：最后一页；2：第一页
     */
    public void updateProgress(int index, int mode) {
        // 章节索引在章节范围内，更新章节读取进度并实例化章节工具类
        if (index >= 0 && index < book.getChapters().size()) {
            book.setChapterIndex(index);
            chapterUtil = new ChapterUtil(book, mode);
        }
    }

    /**
     * 获取上一页按钮
     *
     * @return 上一页
     */
    private JButton getLastPageButton() {
        lastPageButton = new JButton("上一页");
        // 设置此组件的首选大小
        lastPageButton.setPreferredSize(new Dimension(50, 30));
        // 添加行为监听
        lastPageButton.addActionListener(e -> {
            // 上一页文本
            String text = chapterUtil.lastPage();
            if (text.isEmpty()) {
                // 更新为上一章章节索引
                if (lastChapter()) {
                    // 上一章章节的内容
                    text = chapterUtil.currentPage();
                } else {
                    // 更新失败，不启用上一页按钮，退出监听
                    lastPageButton.setEnabled(false);
                    return;
                }
            }
            // 设置文本
            setText(text);
            // 启用下一页按钮
            nextPageButton.setEnabled(true);
        });
        return lastPageButton;
    }

    /**
     * 获取下一页按钮
     *
     * @return 下一页
     */
    private JButton getNextPageButton() {
        nextPageButton = new JButton("下一页");
        // 设置此组件的首选大小
        nextPageButton.setPreferredSize(new Dimension(50, 30));
        // 添加行为监听
        nextPageButton.addActionListener(e -> {
            // 下一页文本内容
            String text = chapterUtil.nextPage();
            // 当前章节没有内容时
            if (text.isEmpty()) {
                // 更新为下一章章节索引
                if (nextChapter()) {
                    // 下一章章节的内容
                    text = chapterUtil.currentPage();
                } else {
                    // 更新失败，不启用下一页按钮，退出监听
                    nextPageButton.setEnabled(false);
                    return;
                }
            }
            // 设置文本
            setText(text);
            // 启用上一页按钮
            lastPageButton.setEnabled(true);
        });
        return nextPageButton;
    }

    /**
     * 获取模式按钮
     *
     * @return 模式切换
     */
    private JButton getModelButton() {
        JButton modelButton = new JButton();
        modelButton.setText(book.getHard() ? "简单" : "困难");
        // 设置此组件的首选大小
        modelButton.setPreferredSize(new Dimension(50, 30));
        // 添加行为监听
        modelButton.addActionListener(e -> {
            book.setHard(!book.getHard());
            chapterUtil.changeMode();
            // 困难模式
            if (book.getHard()) {
                title.setText("Debug");
                textJta.setText("");
                modelButton.setText("简单");
            } else { // 简单模式
                // 释放Window及其子组件及其所有子组件使用的所有本机屏幕资源
                hardReadWidget.dispose();
                modelButton.setText("困难");
            }
            // 设置文本
            setText();
        });
        return modelButton;
    }

    /**
     * 获取目录按钮
     *
     * @return 目录按钮
     */
    private JButton getDirectoryButton() {
        JButton directoryButton = new JButton("目录");
        // 设置此组件的首选大小
        directoryButton.setPreferredSize(new Dimension(50, 30));
        // 目录按钮行为监听
        directoryButton.addActionListener(e -> {
            setText("");
            // 目录页面显示
            UIManager.directoryPage.show();
            isShow = false;
        });
        return directoryButton;
    }

    /**
     * 获取书架按钮
     *
     * @return 书架按钮
     */
    private JButton getBookshelfButton() {
        JButton bookshelfButton = new JButton("书架");
        // 设置此组件的首选大小
        bookshelfButton.setPreferredSize(new Dimension(50, 30));
        bookshelfButton.addActionListener(e -> backBookshelf());
        return bookshelfButton;
    }

    /**
     * 获取首页按钮
     *
     * @return 首页
     */
    private JButton getHomeButton() {
        JButton exitButton = new JButton("首页");
        // 设置此组件的首选大小
        exitButton.setPreferredSize(new Dimension(50, 30));
        exitButton.addActionListener(e -> {
            // 释放Window及其子组件及其所有子组件使用的所有本机屏幕资源
            hardReadWidget.dispose();
            // 展示首页按钮
            UIManager.startPage.show();
            isShow = false;
        });
        return exitButton;
    }

    /**
     * 能否获取上一章章节
     *
     * @return 当更新进度成功时，返回true，否则，false
     */
    private boolean lastChapter() {
        // 上一章章节下标
        int lastIndex = book.getChapterIndex() - 1;
        // 有进度时更新进度
        if (lastIndex >= 0) {
            updateProgress(lastIndex, 1);
            return true;
        }
        return false;
    }

    /**
     * 能否获取下一章章节
     *
     * @return 当更新进度成功时，返回true，否则，false
     */
    private boolean nextChapter() {
        // 下一章章节的下标
        int nextIndex = book.getChapterIndex() + 1;
        // 有进度时更新进度
        if (nextIndex < book.getChapters().size()) {
            updateProgress(nextIndex, 2);
            return true;
        }
        return false;
    }

    /**
     * 添加事件后处理器，即添加快捷键事件监听
     */
    private void addKeyEventPostProcessor() {
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        // 清空快捷键监听处理器
        if (processor != null) {
            manager.removeKeyEventPostProcessor(processor);
        }

        // 处理器
        processor = event -> {
            //　鼠标没有按下或者本页面不显示，跳过
            if (event.getID() != KeyEvent.KEY_PRESSED || !isShow) {
                return false;
            }

            // 获取事件的中文快捷键描述
            String key = KeyFormatUtil.format(event);
            String[] keys = DataCache.readConfig.getKey();

            // 将当前快捷键与配置中的快捷键匹配
            if (key.equals(keys[0])) {
                // 上一页热键
                lastPageButton.doClick();
                return true;
            } else if (key.equals(keys[1])) {
                // 下一页热键
                nextPageButton.doClick();
                return true;
            } else if (key.equals(keys[2])) { // 老板键
                // 困难模式
                if (book.getHard()) {
                    hardReadWidget.setText("");
                } else {
                    // 困难
                    title.setText("Debug");
                    textJta.setText("");
                }
                return true;
            } else if (key.equals(keys[3])) { // 恢复键
                // 目录
                setText();
                return true;
            } else if (key.equals(keys[4]) && scheduler == null) { // 开始自动翻页，书架且定时任务没有初始化，构建定时任务
                // 自动下一页定时任务
                scheduler = ThreadUtil.schedule(ThreadUtil.createScheduledExecutor(1), () -> {
                    // 下一页按钮开启时，点击下一页
                    if (nextPageButton.isEnabled()) {
                        nextPageButton.doClick();
                    }
                }, 1, DataCache.readConfig.getPageTurningSpeed(), TimeUnit.SECONDS, false);
                return true;
            } else if (key.equals(keys[5]) && scheduler != null) {
                // 自动翻页停止
                scheduler.shutdownNow();
                scheduler = null;
                return true;
            }

            return false;
        };
        // 批量添加事件
        manager.addKeyEventPostProcessor(processor);
    }

    /**
     * 设置文本
     */
    private void setText() {
        setText(chapterUtil.currentPage());
    }

    /**
     * 设置文本
     *
     * @param text 内容文本
     */
    private void setText(String text) {
        // 困难模式
        if (book.getHard()) {
            // 未安装
            if (!hardReadWidget.isInstalled()) {
                // 注册状态栏
                hardReadWidget.register();
            }
            // 设置状态栏的文本
            hardReadWidget.setText(text);
        } else {
            // 简单模式
            title.setText(book.getCurrentChapter().getTitle());
            // 设置小说正文
            textJta.setText(text);
        }
    }

    /**
     * 更新书籍进度
     *
     * @return true，更新成功，false，失败
     */
    private boolean updateBookProgress() {
        try {
            LegadoApi legadoApi = new LegadoApi(DataCache.readConfig.getLegadoHost());
            // legado书架map[书籍路径,书籍信息]
            Map<String, LegadoBook> legadoBookMap = legadoApi.getBookshelf().stream().collect(Collectors.toMap(LegadoBook::getBookUrl, b -> b));
            // 当前书籍
            LegadoBook legadoBook = legadoBookMap.get(book.getUrl());
            if (legadoBook != null) {
                // 更新书籍进度
                book.setUrl(legadoBook.getBookUrl());
                book.setChapterIndex(legadoBook.getDurChapterIndex());
                // 章节阅读的进度位置
                book.setChapterPos(legadoBook.getDurChapterPos());
            }
            return true;
        } catch (LegadoApiException e) {
            new LegadoApiException("书籍进度同步失败！").showErrorAlert();
            return false;
        }
    }

    /**
     * 返回书架
     */
    private void backBookshelf() {
        // 释放Window及其子组件及其所有子组件使用的所有本机屏幕资源
        hardReadWidget.dispose();
        // 展示书架页
        UIManager.bookshelfPage.show();
        isShow = false;
    }

    /**
     * 释放此Window及其子组件及其所有子组件使用的所有本机屏幕资源。 也就是说，这些Component的资源将被销毁，它们消耗的任何内存都将被返回给操作系统，并且它们将被标记为不可显示
     */
    public void dispose() {
        hardReadWidget.dispose();
    }

}
